from layer import *
import copy
import time
class x14_setting:
	def __init__(self, maxInputBoard=13, maxOutputBoard=10, sendCmd=None):
		self.MaxInputBoard = maxInputBoard
		self.MaxOutputBoard = maxOutputBoard
		self.MaxView = 16
		self.OutputBoardLayer = 16
		self.device_type = 0x800000
		self.Init()
		self.sendCmd = sendCmd
		self.waitACK_func = None
		self.network = network()
		self.currentLayer = 0
		
		
	def Init(self):
		self.MaxLayer = self.OutputBoardLayer*self.MaxOutputBoard
		self.MaxOutput = 4*self.MaxOutputBoard
		self.MaxInput = 4*self.MaxInputBoard
		self.previewView = view(maxLayer=self.MaxLayer, maxInputBoard=self.MaxInputBoard, maxOutput=self.MaxOutput)
		self.programView = view(maxLayer=self.MaxLayer, maxInputBoard=self.MaxInputBoard, maxOutput=self.MaxOutput)
		self.outputArea = [rect()]*self.MaxOutput
		
		self.view = [view(maxLayer=self.MaxLayer)]*self.MaxView
		for i in range(0, self.MaxView):
			self.view[i] = view(maxLayer=self.MaxLayer, maxInputBoard=self.MaxInputBoard, maxOutput=self.MaxOutput)
			
		self.outputContainerIndex = [0]*self.MaxOutput
		for i in range(0, self.MaxOutput):
			self.outputArea[i] = rect()
		self.inputSet = [inputSet()]*self.MaxInput
		for i in range(0, self.MaxInput):
			self.inputSet[i] = inputSet()
		self.inputSource = [inputSource()]*self.MaxInput
		for i in range(0, self.MaxInput):
			self.inputSource[i] = inputSource()
		self.h264_output = [H264_set()]*(self.MaxOutputBoard+1)
		for i in range(0, self.MaxOutputBoard+1):
			self.h264_output[i] = H264_set()
		self.container = [container()]*self.MaxOutput
		for i in range(0, self.MaxOutput):
			self.container[i] = container()
	def setDeviceType(self, device_type):
		if(device_type == 0x800000):
			self.device_type = device_type
			self.MaxInputBoard = 13
			self.MaxOutputBoard = 10
			self.OutputBoardLayer = 16
			self.Init()
		elif(device_type == 0x700000):
			self.device_type = device_type
			self.MaxInputBoard = 8
			self.MaxOutputBoard = 8
			self.OutputBoardLayer = 8
			self.Init()
		elif(device_type == 0x320000):
			self.device_type = device_type
			self.MaxInputBoard = 4
			self.MaxOutputBoard = 2
			self.OutputBoardLayer = 8
			self.Init()
		elif(device_type == 0x220000):
			self.device_type = device_type
			self.MaxInputBoard = 4
			self.MaxOutputBoard = 4
			self.OutputBoardLayer = 4
			self.Init()
		elif(device_type == 0x628200):
			self.device_type = device_type
			self.MaxInputBoard = 4
			self.MaxOutputBoard = 4
			self.OutputBoardLayer = 4
			self.Init()
		elif(device_type == 0x240000):
			self.device_type = device_type
			self.MaxInputBoard = 4
			self.MaxOutputBoard = 4
			self.OutputBoardLayer = 4
			self.Init()
	def printLayer(self, i):
		print("layer{:02d}:".format(i), self.previewView.layer[i])
	def printProgramLayer(self, i):
		print("layer{:02d}:".format(i), self.programView.layer[i])
	def printAllLayer(self):
		for i in range(0, self.MaxLayer):
			self.printLayer(i)
	def printDisplayLayer(self):
		for i in range(0, self.MaxLayer):
			if(self.previewView.layer[i].alpha):
				self.printLayer(i)
	def printPreviewView(self):
		print("{preview:")
		for i in range(0, self.MaxLayer):
			if(self.previewView.layer[i].alpha):
				self.printLayer(i)
		print("}")
	def printProgramView(self):
		print("{program:")
		for i in range(0, self.MaxLayer):
			if(self.programView.layer[i].alpha):
				self.printProgramLayer(i)
		print("}")
	def printRS1(self):
		print(self.previewView.rs1_set)
	def printAllLayerAlpha(self):
		for i in range(0, self.MaxLayer):
			print("layer{:02d}".format(i),"alpha:{:3d}".format(self.previewView.layer[i].alpha),"pos:",self.previewView.layer[i].pos)
	def printOutputArea(self, i):
		print("outputArea{}:".format(i), self.outputArea[i], "containerIndex:", + self.outputContainerIndex[i])
	def printAllOutputArea(self):
		for i in range(0, self.MaxOutput):
			self.printOutputArea(i)
	def printValidOutputArea(self):
		for i in range(0, self.MaxOutput):
			if(self.outputContainerIndex[i] != 255):
				self.printOutputArea(i)
	def printInputSet(self, i):
		print("inputSet"+"{:2d}:".format(i), self.inputSet[i])
	
	def printAllInputSet(self):
		for i in range(0, self.MaxInput):
			self.printInputSet(i)
	def printValidInputSet(self):
		for i in range(0, self.MaxInput):
			if(self.inputSource[i].type) and (self.inputSource[i].format != 127):
				self.printInputSet(i)
	def printInputSource(self, i):
		print("inputSource"+"{:2d}:".format(i), self.inputSource[i])
	def printAllInputSource(self):
		for i in range(0, self.MaxInput):
			self.printInputSource(i)
	def printContainer(self, i):
		print("container"+"{:2d}:".format(i), self.container[i])
	def printAllContainer(self):
		for i in range(0, self.MaxOutput):
			self.printContainer(i)
	def printValidContainer(self):
		for i in range(0, self.MaxOutput):
			if(self.container[i].onOff):
				self.printContainer(i)
	def printValidInputSource(self):
		for i in range(0, self.MaxInput):
			if (self.inputSource[i].type) and (self.inputSource[i].format != 127):
				self.printInputSource(i)
	def printH264_output(self, i):
		print("h264_output{}:".format(i), self.h264_output[i])
	def SendCmd(self, adr = 0, cmd = 0, dat1 = 0, dat2 = 0, dat3 = 0, dat4 = 0, dataBlock=bytes()):
		if(self.sendCmd):
			return self.sendCmd(adr, cmd, dat1, dat2, dat3, dat4, dataBlock)
		return -1
	def waitACK(self, timeout=1):
		if(self.waitACK_func):
			return self.waitACK_func(timeout)
		return None
	def writeAllLayerAlpha(self):
		dataBlock=bytes()
		alphaLen = len(self.previewView.layer)
		for i in range(0, alphaLen):
			dataBlock = dataBlock+self.previewView.layer[i].alpha.to_bytes(1, byteorder='little')
		for i in range(0, alphaLen):
			dataBlock = dataBlock+self.previewView.layer[i].pos.to_bytes(1, byteorder='little')
		
		#print("dataBlock:", dataBlock)
		return self.SendCmd(cmd=0xf0, dat1=0x02, dataBlock=dataBlock)
	
	def takeToPreview(self):
		return self.SendCmd(cmd=0x78, dat1=0x00, dat2=0x01)
	def takeToProgram(self):
		return self.SendCmd(cmd=0x78, dat1=0x00, dat2=0x00)
	def takeAlpha(self):
		self.writeAllLayerAlpha()
		return self.takeToPreview()
	def writeLayer(self, i):
		dataBlock = self.previewView.layer[i].toBytes()
		return self.SendCmd(cmd=0xf0, dat1=0x01, dat2=i, dataBlock=dataBlock)
	def readLayer(self, i):
		return self.SendCmd(cmd=0xf1, dat1=0x00, dat2=i)
		
	def readAllLayer(self):
		result = -1
		for i in range(0, self.MaxLayer):
			result = self.readLayer(i)
		return result
	def readH264_output(self, i):
		self.SendCmd(cmd=0xf1, dat1=0x20, dat2=0x00, dat3=i)
		return self.SendCmd(cmd=0xf1, dat1=0x20, dat2=0x01, dat3=i)
	def writeH264_output(self, i):
		dataBlock = self.h264_output[i].networkToBytes()
		dataBlock += i.to_bytes(1, byteorder='little')
		self.SendCmd(cmd=0xf0, dat1=0x20, dat2=0x00, dataBlock=dataBlock)
		print("f02000:", len(dataBlock), dataBlock)
		dataBlock = self.h264_output[i].capToBytes()
		dataBlock += i.to_bytes(1, byteorder='little')
		print("f02001:", len(dataBlock), dataBlock)
		return self.SendCmd(cmd=0xf0, dat1=0x20, dat2=0x01, dataBlock=dataBlock)
	def readInputSet(self, i):
		return self.SendCmd(cmd=0xf1, dat1=0x09, dat2=i)
	def readAllInputSet(self):
		result = -1
		for i in range(0, self.MaxInput):
			result = self.readInputSet(i)
		return result
	def readInputBoard(self, i):
		return self.SendCmd(cmd=0xf1, dat1=0x0a, dat2=i)
	def readAllInputSource(self):
		result = -1
		for i in range(0, self.MaxInputBoard):
			result = self.readInputBoard(i)
	def readOutputArea(self):
		return self.SendCmd(cmd=0xf1, dat1=0x05)
	def writeOutputArea(self):
		dataBlock = bytes()
		for i in range(0, self.MaxOutput):
			dataBlock = dataBlock+self.outputArea[i].toBytes()
		for i in range(0, self.MaxOutput):
			dataBlock = dataBlock+self.outputContainerIndex[i].to_bytes(1, byteorder='little')
		return self.SendCmd(cmd=0xf0, dat1=0x05, dataBlock=dataBlock)
	def findFreeLayer(self):
		for i in range(0, self.MaxLayer):
			if (self.previewView.layer[i].alpha == 0):
				return i
		return -1
	def displayInput(self, input=0, scale=rect()):
		freeLayer = self.findFreeLayer()
		if(freeLayer == -1):
			return -1
		layer1 = self.previewView.layer[freeLayer]
		layer1.crop = copy.copy(self.inputSet[input].scale)
		layer1.scale = copy.copy(scale)
		layer1.input = input
		layer1.alpha = 128
		self.currentLayer = freeLayer
		return self.writeLayer(freeLayer)
	def setInputToOutput(self, input=0, output=0):
		return self.displayInput(input, self.outputArea[output])
	def setInputToOutputAndTake(self, input=0, output=0):
		self.setInputToOutput(input, output)
		return self.takeAlpha()
	def set4InputToOutput(self, input1=0, input2=1, input3=2, input4=3, output=0):
		scale = copy.copy(self.outputArea[output]);
		scale.w = (scale.w//2)
		scale.h = (scale.h//2)
		self.displayInput(input1, scale);
		
		scale = copy.copy(self.outputArea[output]);
		scale.w = scale.w//2
		scale.h = scale.h//2
		scale.x = scale.x+scale.w
		self.displayInput(input2, scale);
		
		scale = copy.copy(self.outputArea[output]);
		scale.w = scale.w//2
		scale.h = scale.h//2
		scale.y = scale.y+scale.h
		self.displayInput(input3, scale);
		
		scale = copy.copy(self.outputArea[output]);
		scale.w = scale.w//2
		scale.h = scale.h//2
		scale.x = scale.x+scale.w
		scale.y = scale.y+scale.h
		return self.displayInput(input4, scale);
	def set4InputToOutputAndTake(self, input1=0, input2=1, input3=2, input4=3, output=0):
		self.set4InputToOutput(input1, input2, input3, input4, output)
		return self.takeAlpha()
	def clearAllLayer(self):
		for i in range(0, self.MaxLayer):
			self.previewView.layer[i].alpha = 0
	def clearAllLayerAndTake(self):
		self.clearAllLayer()
		self.writeAllLayerAlpha()
		return self.takeToPreview()
	def saveCurrentView(self):
		return self.SendCmd(cmd=0x68, dat1=0x1a)
	def saveView(self, index):
		return self.SendCmd(cmd=0x68, dat1=0x1a, dat2=0x01, dat3=index)
	def loadView(self, index):
		return self.SendCmd(cmd=0x68, dat1=0x18, dat2=index)
	def loadViewAndTake(self, index):
		self.loadView(index)
		return self.takeToPreview()
	def syncRS1(self):
		for i in range(0, self.MaxInputBoard):
			self.SendCmd(cmd=0xf1, dat1=0x2b, dat2=i)
		for i in range(0, self.MaxOutput):
			self.SendCmd(cmd=0xf1, dat1=0x2c, dat2=i)
	def sync(self):
		self.SendCmd(cmd=0x68, dat1=0x01)
		time.sleep(0.5)
		self.readAllLayer()
		self.readAllInputSource()
		self.readAllInputSet()
		self.readOutputArea()
		self.syncNetwork()
	def sync1(self):
		self.SendCmd(cmd=0x68, dat1=0x01)
		#self.waitACK()
		self.SendCmd(cmd=0xf1, dat1=0x00, dat2=0xff) #self.readAllLayer()
		#self.waitACK()
		self.SendCmd(cmd=0xf1, dat1=0x06, dat2=0xff) # read all program layer
		#self.waitACK()
		self.readAllInputSource()
		#self.waitACK()
		self.SendCmd(cmd=0xf1, dat1=0x09, dat2=0xff)#self.readAllInputSet()
		#self.waitACK()
		self.readOutputArea()
		#self.waitACK()
		self.readContainer()
		#self.waitACK()
		self.syncNetwork()
		#self.waitACK()
	def writeDHCP(self, onOff):
		return self.SendCmd(cmd=0x8e, dat1=0x02, dat2=onOff)
	def readDHCP(self):
		return self.SendCmd(cmd=0x8e, dat1=0x03)
	def readMAC_addr(self):
		self.SendCmd(cmd=0x8e, dat1=0x05)
		return self.SendCmd(cmd=0x8e, dat1=0x07)
	def writeIP_addr(self, IP1, IP2, IP3, IP4):
		return self.SendCmd(cmd=0x88, dat1=IP1%256, dat2=IP2%256, dat3=IP3%256, dat4=IP4%256)
	def readIP_addr(self):
		return self.SendCmd(cmd=0x89)
	def writeNetMask(self, IP1, IP2, IP3, IP4):
		return self.SendCmd(cmd=0x84, dat1=IP1%256, dat2=IP2%256, dat3=IP3%256, dat4=IP4%256)
	def readNetMask(self):
		return self.SendCmd(cmd=0x85)
	def writeDefGW(self, IP1, IP2, IP3, IP4):
		return self.SendCmd(cmd=0x8c, dat1=IP1%256, dat2=IP2%256, dat3=IP3%256, dat4=IP4%256)
	def readDefGW(self):
		return self.SendCmd(cmd=0x8d)
	def syncNetwork(self):
		self.readDHCP()
		self.readIP_addr()
		self.readNetMask()
		self.readDefGW()
		self.readMAC_addr()
	def writeNetwork(self):
		result = self.writeDHCP(self.network.DHCP)
		if(self.network.DHCP == 0):
			IP = self.network.IP_adr
			self.writeIP_addr(IP[0], IP[1], IP[2], IP[3])
			IP = self.network.DefGW
			self.writeDefGW(IP[0], IP[1], IP[2], IP[3])
			IP = self.network.NetMask
			result = self.writeNetMask(IP[0], IP[1], IP[2], IP[3])
		return result
	def readContainer(self):
		return self.SendCmd(cmd=0xf1, dat1=0x3b)
	def writeContainer(self):
		dataBlock = bytes()
		for i in range(0, self.MaxOutput):
			dataBlock += self.container[i].toBytes()
		return self.SendCmd(cmd=0xf0, dat1=0x3b, dataBlock=dataBlock)
	def printNetwork(self):
		print(self.network)
	def takeContainer(self, pst_or_pgm, *takeData):
		dataBlock = bytes()
		for i in range(0, len(takeData)):
			dataBlock += takeData[i].to_bytes(1, byteorder='little')
			
		if (len(takeData)<self.MaxOutput):
			remain = self.MaxOutput-len(takeData)
			for i in range(0, remain):
				dataBlock += bytes(1)
		print(len(dataBlock))
		print(dataBlock)
		return self.SendCmd(cmd=0xf0, dat1=0x38, dat2=pst_or_pgm, dataBlock=dataBlock)
if __name__ == "__main__":
	x14_set = x14_setting()
	print(len(x14_set.previewView.layer))
	print(x14_set.previewView.layer[0])
	print(len(x14_set.outputArea))
	print(x14_set.outputArea[0])
	x14_set.printAllLayer()
	x14_set.printAllOutputArea()
	x14_set.printAllInputSet()
	x14_set.writeAllLayerAlpha()
	x14_set.printAllLayerAlpha()
	x14_set.setInputToOutput()
	x14_set.set4InputToOutputAndTake()
	x14_set.printAllInputSource()
	x14_set.writeNetwork()
	x14_set.printNetwork()
	x14_set.printH264_output(10)